package cn.tedu._03vehicle.base.interceptors;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.concurrent.ConcurrentHashMap;

/*
 * 拦截器：限流功能拦截器
 */
@Slf4j
public class RateLimitInterceptor implements HandlerInterceptor {
    private static final int MAX_REQUEST_PER_MINUTE = 3;
    private static final int WINDOW_SIZE_SECONDS = 60;
    //1.定义一个hasMap用来存储ip地址和访问次数
    private final ConcurrentHashMap<String, Integer> ipClienCounts = new ConcurrentHashMap<>();
    //2.定义一个hasMap存ip地址最后访问时间
    private final ConcurrentHashMap<String, LocalDateTime> ipClienTimes = new ConcurrentHashMap<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.先获取客户端的ip地址
        String ipAddress = request.getRemoteAddr();
        //2.获取并判断时间
        LocalDateTime lastTime = ipClienTimes.get(ipAddress);
        if (lastTime == null || LocalDateTime.now().isAfter(lastTime.plusSeconds(WINDOW_SIZE_SECONDS))) {//第一次访问或者访问时间已经过期
            //计数器清零
            ipClienCounts.put(ipAddress, 0);
            //记录访问时间
            ipClienTimes.put(ipAddress, LocalDateTime.now());
        }
        //计数器加1
        Integer count = ipClienCounts.merge(ipAddress, 1, Integer::sum);//1、key：ip地址，2、value：1，3、合并函数
        if (count > MAX_REQUEST_PER_MINUTE) {//超过限制
            throw new RuntimeException("访问次数过多，请稍后再试");
        }
        return true;
    }
}
































